(旧Siv3D) ゲームでよく見るカットインエフェクト
https://gyazo.com/744d7bf014257f93e63f7cc6f300eb47
code:cutinfx.cpp
struct ScrollLines
{
Array<RectF> lines;
int frame = 0;
const int duration;
const int fade;
ScrollLines(const int duration, const int fade) : duration(duration), fade(fade)
{
}
void update()
{
if (InRange(frame, 0, duration))
{
// Generate lines
if (frame % 2 == 0)
{
const double length = Random(40.0, 200.0);
const double width = Random(0.5, 1.5);
const Vec2 pos = Vec2(-length, Random(Window::Height()));
lines.emplace_back(pos, length, width);
}
// Move lines
for (auto& r : lines)
{
r.moveBy(r.w * 0.3, 0);
}
// Remove lines
Erase_if(lines, [](auto& r) { return r.x > Window::Width(); });
int alpha = 255;
if (frame < fade) alpha = 255 * frame / (double)fade;
if (frame > duration - fade) alpha -= 255 * (frame - (duration - fade)) / (double)fade;
// Draw BG
Window::ClientRect().draw(Color(0, alpha / 3));
// Draw lines
for (auto& r : lines)
{
for (int i : step(3))
{
r.movedBy(-r.w * 0.3 * (i + 1), 0).draw(Alpha(alpha / (i + 1)));
}
r.draw(Alpha(alpha));
}
}
++frame;
}
};
struct Banner
{
int frame = 0;
const int duration;
const int bannerOpen = 16;
const int bannerClose = 16;
const String text;
const Font font{ 32, Typeface::Bold, FontStyle::Italic };
Banner(const int duration, const String& text) : duration(duration), text(text)
{
}
void update()
{
if (InRange(frame, 0, duration))
{
// Open / Close banner
double width = 70.0;
if (InRange(frame, 0, bannerOpen))
{
width *= EaseOut<Easing::Cubic>(frame / (double)bannerOpen);
}
if (InRange(frame, duration - bannerClose, duration))
{
width *= 1.0 - EaseIn<Easing::Cubic>((frame - (duration - bannerClose)) / (double)bannerClose);
}
RectF(0, Window::Height() / 2 - width / 2, Window::Width(), width).draw(Palette::Deepskyblue);
// mini lines
if (frame > bannerOpen)
{
const double y1 = 5 * (frame - bannerOpen);
const double y2 = 5 * (frame - bannerOpen - 16);
const double baseY = Window::Center().y;
for (int i : step(4))
{
const double Y1 = 50.0 * (i + 1);
const double Y2 = 50.0 * (i + 1) + (20.0 - i * 4.5);
if (y1 > Y1 && y2 < Y2)
{
RectF(0, Min(baseY + y1, baseY + Y2), Window::Width(), Max(baseY + y2, baseY + Y1) - Min(baseY + y1, baseY + Y2)).draw(Palette::Royalblue);
RectF(0, Max(baseY - y1, baseY - Y2), Window::Width(), Min(baseY - y2, baseY - Y1) - Max(baseY - y1, baseY - Y2)).draw(Palette::Royalblue);
}
}
}
// Text
const int wait = 8;
const int durationText = duration - wait * 2;
const Rect region = font.region(text);
const double startX = -region.center.x;
const double moveDist = Window::Width() + region.w;
const Vec2 textPos(
startX + moveDist * (EaseIn<Easing::Expo>((frame - wait) / (double)durationText) + EaseOut<Easing::Expo>((frame - wait) / (double)durationText)) / 2.0,
Window::Center().y);
font(text).drawCenter(textPos.movedBy(2, 2), Palette::Dodgerblue);
font(text).drawCenter(textPos);
}
++frame;
}
};
void Main()
{
Graphics::SetBackground(Palette::Midnightblue);
const int scrollLinesStart = 30;
const int scrollLinesDuration = 180;
const int scrollLinesFade = 32;
const int bannerWait = 16;
const int bannerStart = scrollLinesStart + bannerWait;
ScrollLines scrollLines(scrollLinesDuration, scrollLinesFade);
Banner banner(scrollLinesDuration - bannerWait * 2, L"SIV3D CUT IN EFFECT");
int frame = 0;
frame = 0;
scrollLines.frame = 0;
banner.frame = 0;
};
while (System::Update())
{
if (Input::KeyEnter.clicked)
{
reset();
}
if (frame > scrollLinesStart)
{
scrollLines.update();
}
if (frame > bannerStart)
{
banner.update();
}
++frame;
}
}